/**
 * Sprite Manager.
 *
 * Released under Apache License, Version 2.0.
 */

package bsp.android.spritefwk;

import java.util.Vector;

import android.content.res.Resources;
import android.graphics.Canvas;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

public class SpriteManager
{
	protected Vector<Sprite> mSprites;
	protected Sprite mPreviousSelection;
	protected SpriteSelectionChangeListener mCommonListener;
	protected ImageHolder mStandardImageHolder, mSelectedImageHolder;
	
	public SpriteManager(Resources res, int standardImageId, int selectedImageId, SpriteSelectionChangeListener listener)
	{
		mSprites = new Vector<Sprite>();
		mCommonListener = listener;
		mPreviousSelection = null;
		mStandardImageHolder = new ImageHolder(res, standardImageId);
		mSelectedImageHolder = new ImageHolder(res, selectedImageId);
	}
	
	/**
	 * Add a sprite.
	 * 
	 * @param id Sprite ID.
	 * @param listener Sprite specific listener.
	 * @param posX X coordinate of starting location of sprite on the screen.
	 * @param posY Y coordinate of starting location of sprite on the screen.
	 * @param width Width of the sprite.
	 * @param height Width of the sprite.
	 * @param offsetX X coordinate of starting location of the sprite in the standard and selected images.
	 * @param offsetY Y coordinate of starting location of the sprite in the standard and selected images.
	 */
	public void addSprite(String id, SpriteSelectionChangeListener listener, int posX, int posY, int width, int height, int offsetX, int offsetY)
	{
		Sprite sp = new Sprite(id, listener, mStandardImageHolder, mSelectedImageHolder, posX, posY, width, height, offsetX, offsetY);
		mSprites.add(sp);
	}
	
	/**
	 * Add a sprite.
	 * 
	 * @param sp
	 */
	public void addSprite(Sprite sp)
	{
		mSprites.add(sp);
	}
	
	/**
	 * Set the listener common to all the sprites.
	 * 
	 * @param listener
	 */
	public void setCommondListener(SpriteSelectionChangeListener listener)
	{
		mCommonListener = listener;
	}
	
	/**
	 * Get the listener common to all the sprites.
	 * 
	 * @return
	 */
	public SpriteSelectionChangeListener getCommonListener()
	{
		return mCommonListener;
	}
	
	public void setSelectionForAll(boolean flag)
	{
		int size = mSprites.size();
		Sprite sp;
		for ( int i = 0; i < size; i++ ) {
			sp = mSprites.get(i);
			sp.setSelected(flag);
			if ( sp.hasListener() == false ) {
				if ( mCommonListener != null ) {
					mCommonListener.selectionChanged(sp.getId(), flag);
				}
			}
		}
	}
	
	public Sprite selectSprite(int x, int y)
	{
		int size = mSprites.size();
		Sprite retVal = null, sp;
		
		for ( int i = 0; i < size; i++ ) {
			sp = mSprites.get(i);
			if ( true == sp.isInside(x, y) ) {
				retVal = sp;
				break;
			}
		}
		
		return retVal;
	}
	
	public boolean checkSelectedByPosition(int idx)
	{
		boolean retVal = false;

		if ( idx > 0 && idx < mSprites.size() ) {
			Sprite sp = mSprites.get(idx);
			retVal = sp.isSelected();
		}
		
		return retVal;
	}
	
	public boolean checkSelectedById(String id)
	{
		boolean retVal = false;

		int size = mSprites.size();
		Sprite sp;
		for ( int i = 0; i < size; i++ ) {
			sp = mSprites.get(i);
			if ( true == id.equals(sp.getId()) ) {
				retVal = sp.isSelected();
			}
		}
		
		return retVal;
	}
	
	/**
	 * Draw the sprites.
	 * 
	 * @param c
	 */
	public void draw(Canvas c)
	{
		int size = mSprites.size();
		Sprite sp;
		for ( int i = 0; i < size; i++ ) {
			sp = mSprites.get(i);
			sp.draw(c);
		}
	}
	
	/**
	 * Draw the sprites.
	 * 
	 * @param holder
	 */
	public void draw(SurfaceHolder holder)
	{
		Canvas c = holder.lockCanvas();
		draw(c);
		holder.unlockCanvasAndPost(c);
	}
	
	protected void setSelectionFlagForSprite(Sprite sprite, boolean flag)
	{
		if ( sprite != null ) {
			sprite.setSelected(flag);
			/*
			 * If sprite does not have a listener, send message to listener
			 * common to all sprites.
			 */
			if ( sprite.hasListener() == false ) {
				if ( mCommonListener != null ) {
					mCommonListener.selectionChanged(sprite.getId(), flag);
				}
			}
		}
	}
	
	/**
	 * Handle touch event.
	 * 
	 * @param event
	 */
	public void handleTouchEvent(MotionEvent event)
	{
		int x = (int)event.getX();
		int y = (int)event.getY();
		
		Sprite sp = selectSprite(x, y);

		if ( event.getAction() == MotionEvent.ACTION_DOWN ) {
			handleActionDown(sp, x, y);
		} else if ( event.getAction() == MotionEvent.ACTION_MOVE ) {
			handleActionMove(sp, x, y);
		} else if ( event.getAction() == MotionEvent.ACTION_UP ) {
			handleActionUp(sp, x, y);
		}
	}
	
	/**
	 * Handle ACTION_DOWN event.
	 * 
	 * @param sp
	 * @param x
	 * @param y
	 */
	public void handleActionDown(Sprite sp, int x, int y)
	{
		setSelectionFlagForSprite(mPreviousSelection, false);
		setSelectionFlagForSprite(sp, true);
		mPreviousSelection = sp;
	}
	
	/**
	 * Handle ACTION_UP event.
	 * 
	 * @param sp
	 * @param x
	 * @param y
	 */
	public void handleActionUp(Sprite sp, int x, int y)
	{
		setSelectionFlagForSprite(sp, false);
		mPreviousSelection = null;
	}
	
	/**
	 * Handle ACTION_MOVE event.
	 * 
	 * @param sp
	 * @param x
	 * @param y
	 */
	public void handleActionMove(Sprite sp, int x, int y)
	{
		/*
		 * If no sprite has been selected and there is a prev selection
		 * for the sprite, we have moved out of the selected sprite. Hence
		 * we will unselect previously selected sprite.
		 */
		setSelectionFlagForSprite(mPreviousSelection, false);
		
		/*
		 * If we move into a sprite, we will select the sprite. If there is a prev
		 * selection for the sprite, we will unselect it.
		 * 
		 * If while moving, we remain inside the same sprite that was selected
		 * by action down earlier, we will not take any action.
		 */
		if ( sp != mPreviousSelection ) {
			setSelectionFlagForSprite(mPreviousSelection, false);
		}
		setSelectionFlagForSprite(sp, true);
		mPreviousSelection = sp;
	}
	
	public void cleanup()
	{
		for ( Sprite s : mSprites ) {
			s.cleanup();
		}
		mSprites.clear();
		mSprites = null;
		mPreviousSelection = null;
		mCommonListener = null;
		mStandardImageHolder.cleanup();
		mStandardImageHolder = null;
		mSelectedImageHolder.cleanup();
		mSelectedImageHolder = null;
	}
}

/* end */
